package cn.stylefeng.guns.modular.business.frequency.userawardbase.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.exception.enums.StatusExceptionEnum;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.AndaPageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.modular.business.custom.constant.PublicCommon;
import cn.stylefeng.guns.modular.business.custom.enums.BonusTypeEnum;
import cn.stylefeng.guns.modular.business.frequency.orderbonus.entity.OrderBonus;
import cn.stylefeng.guns.modular.business.frequency.orderbonus.mapper.OrderBonusMapper;
import cn.stylefeng.guns.modular.business.frequency.orderroyalty.entity.OrderRoyalty;
import cn.stylefeng.guns.modular.business.frequency.orderroyalty.mapper.OrderRoyaltyMapper;
import cn.stylefeng.guns.modular.business.frequency.siterelation.entity.SiteRelation;
import cn.stylefeng.guns.modular.business.frequency.syssite.mapper.SysSiteMapper;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.entity.UserAwardBase;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.mapper.UserAwardBaseMapper;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.model.param.UserAwardBaseParam;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.model.result.PkgUserAwardBase;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.service.UserAwardBaseService;
import cn.stylefeng.guns.modular.business.frequency.userawardbase.enums.UserAwardBaseExceptionEnum;
import cn.stylefeng.guns.modular.business.util.BusinessUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 网点人员提成设置表 服务实现类
 *
 * @author yujie
 * @date 2023/05/09 17:15
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserAwardBaseServiceImpl extends ServiceImpl<UserAwardBaseMapper, UserAwardBase> implements UserAwardBaseService {

    @Autowired
    private BusinessUtil businessUtil;
    @Resource
    private SysSiteMapper siteMapper;
    @Resource
    private OrderBonusMapper orderBonusMapper;
    @Autowired
    private OrderRoyaltyMapper orderRoyaltyMapper;

    @Override
    public ResponseData page(UserAwardBaseParam userAwardBaseParam) {

        //获取租户id
        Long tenantId = businessUtil.getTenantId();
        userAwardBaseParam.setTenantId(tenantId);
        // 构造条件
        Page<SiteRelation> page =  this.baseMapper.getPage(PageFactory.defaultPage(),userAwardBaseParam);
        return ResponseData.andaSuccess(new AndaPageResult<>().AndaPageResult(page,userAwardBaseParam));



        // 查询分页结果

    }

    @Override
    public List<UserAwardBase> list(UserAwardBaseParam userAwardBaseParam) {

        // 构造条件
        LambdaQueryWrapper<UserAwardBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserAwardBase::getStatus, 1);
        queryWrapper.eq(UserAwardBase::getTenantId,businessUtil.getTenantId());
        return this.list(queryWrapper);
    }

    @Override
    public void add(UserAwardBaseParam userAwardBaseParam) {
        if(!ObjectUtil.equal(userAwardBaseParam.getRoyaltyType(),PublicCommon.路线)){
            this.list(new QueryWrapper<UserAwardBase>().lambda()
                    .eq(UserAwardBase::getTenantId,businessUtil.getTenantId())
                    .eq(UserAwardBase::getSiteId,userAwardBaseParam.getSiteId()));
        }

        if (userAwardBaseParam.getUserAwardBaseParamList()!=null && userAwardBaseParam.getUserAwardBaseParamList().size()>0){
            List<UserAwardBase> userAwardBaseList = new ArrayList<>();
            for (UserAwardBaseParam param : userAwardBaseParam.getUserAwardBaseParamList()) {
                UserAwardBase userAwardBase = new UserAwardBase();
                BeanUtils.copyProperties(param, userAwardBase);
                userAwardBase.setName(userAwardBaseParam.getName());
                userAwardBase.setRoyaltyType(userAwardBaseParam.getRoyaltyType());
                userAwardBase.setSiteId(userAwardBaseParam.getSiteId());
                userAwardBase.setTenantId(businessUtil.getTenantId());
                userAwardBaseList.add(userAwardBase);
            }
            this.saveBatch(userAwardBaseList);
        }else {
            // 将dto转为实体
            UserAwardBase userAwardBase = new UserAwardBase();
            BeanUtils.copyProperties(userAwardBaseParam, userAwardBase);
            userAwardBase.setTenantId(businessUtil.getTenantId());
            this.save(userAwardBase);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(UserAwardBaseParam userAwardBaseParam) {
      this.removeById(userAwardBaseParam.getId());
    }

    @Override
    public void edit(UserAwardBaseParam userAwardBaseParam) {
        this.remove(new QueryWrapper<UserAwardBase>().lambda().eq(UserAwardBase::getTenantId,businessUtil.getTenantId()));

        if(!ObjectUtil.equal(userAwardBaseParam.getRoyaltyType(),PublicCommon.路线)){
            this.list(new QueryWrapper<UserAwardBase>().lambda()
                    .eq(UserAwardBase::getTenantId,businessUtil.getTenantId())
                    .eq(UserAwardBase::getSiteId,userAwardBaseParam.getSiteId()));
        }

        if (userAwardBaseParam.getUserAwardBaseParamList()!=null && userAwardBaseParam.getUserAwardBaseParamList().size()>0){
            List<UserAwardBase> userAwardBaseList = new ArrayList<>();
            for (UserAwardBaseParam param : userAwardBaseParam.getUserAwardBaseParamList()) {
                UserAwardBase userAwardBase = new UserAwardBase();
                BeanUtils.copyProperties(param, userAwardBase);
                userAwardBase.setName(userAwardBaseParam.getName());
                userAwardBase.setRoyaltyType(userAwardBaseParam.getRoyaltyType());
                userAwardBase.setTenantId(businessUtil.getTenantId());
                userAwardBaseList.add(userAwardBase);
            }
            this.saveBatch(userAwardBaseList);
        }else {
            // 将dto转为实体
            UserAwardBase userAwardBase = new UserAwardBase();
            BeanUtils.copyProperties(userAwardBaseParam, userAwardBase);
            userAwardBase.setTenantId(businessUtil.getTenantId());
            this.save(userAwardBase);
        }
    }

    @Override
    public UserAwardBase detail(UserAwardBaseParam userAwardBaseParam) {
        return this.queryUserAwardBase(userAwardBaseParam);
    }

    @Override
    public void changeStatus(UserAwardBaseParam userAwardBaseParam) {
        Long id = userAwardBaseParam.getId();
        Integer status = userAwardBaseParam.getStatus();



        // 更新枚举，更新只能更新未删除状态的
        LambdaUpdateWrapper<UserAwardBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
            .eq(UserAwardBase::getId, id).set(UserAwardBase::getStatus, status);
        boolean update = this.update(updateWrapper);
        if (!update) {
            throw new ServiceException(StatusExceptionEnum.UPDATE_STATUS_ERROR);
        }
    }

    @Override
    public List<PkgUserAwardBase> getUserAwardBaseList(String siteId, String month) {
        List<PkgUserAwardBase> list = new ArrayList<>();
        if (StringUtils.isBlank(month)) {
            // 获取当前月份 yyyy-MM-dd
            String currentDayStr = DateUtil.today();
            month = currentDayStr.substring(0, 7).replace("-", "");
        }
        // 网点下的所有用户ID
        List<String> userIds = siteMapper.getUserIds(siteId);
        if (userIds != null && userIds.size() > 0) {
            list = this.baseMapper.getUserAwardBaseList(userIds,siteId);
            for (PkgUserAwardBase award : list) {
                List<String> uids = new ArrayList<>();
                uids.add(award.getUserId());
                // 奖金明细
                List<OrderBonus> orderBonusList = orderBonusMapper.getByUserIdsAndMonth(uids, month);
                if (orderBonusList != null && orderBonusList.size() > 0) {
                    // 制单
                    Stream<BigDecimal> stream1 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.CREATE_ORDER.type).map(OrderBonus::getFee);
                    award.setCreateFee(stream1.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setCreateCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.CREATE_ORDER.type).count());
                    // 提短
                    Stream<BigDecimal> stream2 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.FREE_PICK_CAR.type).map(OrderBonus::getFee);
                    award.setPickFreeFee(stream2.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setPickFreeCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.FREE_PICK_CAR.type).count());
                    // 验车
                    Stream<BigDecimal> stream3 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.VERIFY_CAR.type).map(OrderBonus::getFee);
                    award.setVerifyFee(stream3.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setVerifyCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.VERIFY_CAR.type).count());
                    // 发车
                    Stream<BigDecimal> stream4 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.TRANSPORT.type).map(OrderBonus::getFee);
                    award.setTransportFee(stream4.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setTransportCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.TRANSPORT.type).count());
                    // 交付
                    Stream<BigDecimal> stream5 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.DELIVERY.type).map(OrderBonus::getFee);
                    award.setDeliveryFee(stream5.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setDeliveryCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.DELIVERY.type).count());
                    // 指派提车
                    Stream<BigDecimal> stream6 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.ASSIGN_PICK.type).map(OrderBonus::getFee);
                    award.setPickFee(stream6.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setPickCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.ASSIGN_PICK.type).count());
                    // 签收
                    Stream<BigDecimal> stream7 = orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.SIGN.type).map(OrderBonus::getFee);
                    award.setSignFee(stream7.reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setSignCount(orderBonusList.stream().filter(orderBonus -> orderBonus.getType() == BonusTypeEnum.SIGN.type).count());
                }
                // 提成明细
                List<OrderRoyalty> royaltyList = orderRoyaltyMapper.getListByUserIdsAndMonth(uids, month);
                if (royaltyList != null && royaltyList.size() > 0) {
                    award.setRoyaltyFee(royaltyList.stream().map(OrderRoyalty::getRoyaltyFee).reduce(BigDecimal.ZERO, BigDecimal::add));
                    award.setRoyaltyCount((long) royaltyList.size());
                }
            }
        }
        return list;
    }

    @Override
    public boolean checkParam(UserAwardBaseParam userAwardBaseParam, StringBuilder errorMessage) {
        //路线类型以外的不可以重复添加
        if (userAwardBaseParam.getRoyaltyType()!=3){
            List<UserAwardBase> list = this.list(new QueryWrapper<UserAwardBase>().lambda().eq(UserAwardBase::getTenantId, businessUtil.getTenantId()));
            if (list!=null&&list.size()>0){
                errorMessage.append("已设置过提成类型,请勿重复添加");
                return true;
            }
        }else {
            List<UserAwardBase> list1 = this.list(new QueryWrapper<UserAwardBase>().lambda().eq(UserAwardBase::getTenantId, businessUtil.getTenantId()).ne(UserAwardBase::getRoyaltyType,3));
            if (list1!=null&&list1.size()>0){
                errorMessage.append("已设置过提成类型,请勿重复添加");
                return true;
            }
            //路线类型不可以重复添加城市
            List<String> collect = userAwardBaseParam.getUserAwardBaseParamList().stream().map(UserAwardBaseParam::getCityCode).collect(Collectors.toList());
            Set<String> set = new HashSet<>(collect);
            List<String> uniqueList = new ArrayList<>(set);
            if (collect.size()!= uniqueList.size()){
                errorMessage.append("不可添加重复城市");
                return true;
            }
            List<UserAwardBase> list = this.list(new QueryWrapper<UserAwardBase>().lambda().in(UserAwardBase::getCityCode, collect).eq(UserAwardBase::getTenantId,businessUtil.getTenantId()));
            if(list!=null && list.size()>0){
                errorMessage.append("路线提成类型请勿添加重复的城市类型");
                return true;
            }
        }

        return false;
    }


    /**
     * 获取网点人员提成设置表
     *
     * @author yujie
     * @since 2023/05/09 17:15
     */
    private UserAwardBase queryUserAwardBase(UserAwardBaseParam userAwardBaseParam) {
        UserAwardBase userAwardBase = this.getById(userAwardBaseParam.getId());
        if (ObjectUtil.isEmpty(userAwardBase)) {
            throw new ServiceException(UserAwardBaseExceptionEnum.NOT_EXISTED);
        }
        return userAwardBase;
    }
}